home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 1.iso
/
ARGONET
/
PD
/
GRAPHICS
/
GIF2RPC.SPK
/
source
/
s
/
map8_accurat
< prev
next >
Wrap
Text File
|
1995-12-29
|
5KB
|
142 lines
; map8_accurate.s
; MACHINE: RISC OS
; LANGUAGE: OBJASM assembler
; AUTHOR: Cy Booker, cy@cheepnis.demon.co.uk
; LICENSE: FreeWare, Copyright (c) Cy Booker 1995
; PURPOSE: Given an arbitary 48-bit colour, what is the closest 8-bit colour number?
; HISTORY: 1995.12.29 CJB tidied up comments
GET OS:Hdr.os
;
; in middle we have |intensity-difference| <-- 0xffff
; so |i|^2 <= 0xffffe0001
; and so to compensate we will have to shift right by quite a lot!
;
; the weights we want are:
; Red * 0.212671 * 358 ~= 76 /512 ~= 0x0.2610 ~= 0x0.26
; Green * 0.715160 * 358 ~= 256 /512 ~= 0x0.8000 ~= 0x0.80
; Blue * 0.072169 * 358 ~= 26 /512 ~= 0x0.0ce6 ~= 0x0.0d
;
; note we will use the *358 because it makes the inline multiplies very quick
; note we divide by 512 so that total difference fits into 32 unsigned bits
;
EXPORT map_scaled_rgb_to_palette_index
AREA |ARM$$code|, CODE, READONLY
ROUT
str RN a1
orig_r RN a2
orig_g RN a3
orig_b RN a4
dmin RN v1
i RN v2
palette RN v3
r RN v4 ; implicit r < g
g RN v5 ; implicit r < g < b
b RN v6 ; implicit g < b
d RN ip
t RN lr
best RN str ; implicitly a1 as well
;
; In R0 -> structure
; R0+(3*4) -> array [N][3] of palette intensity [0, 0xffff]
; R0+(4*4) = number of colours (N)
; R1 = red nominally [0, 0xffff], but clipped as necessary
; R2 = green nominally [0, 0xffff], but clipped as necessary
; R3 = blue nominally [0, 0xffff], but clipped as necessary
; Out R0 = palette index
; structure[0] = error in approximating red intensity
; structure[1] = error in approximating green intensity
; structure[2] = error in approximating blue intensity
;
; the test8bpp program shows this to produce exactly the same result as the
; floating point algorithm for a single run of 1000 random values
;
ROUT
map_scaled_rgb_to_palette_index
STMFD sp!, {a1, v1-v6, lr} ; store a1 as temporary
MOV lr, #0xff00
ORR lr, lr, #0xff
CMP orig_r, #0x10000 ; ensure in range [0, 0xffff]
MOVHS orig_r, #0
MOVGE orig_r, lr
CMP orig_g, #0x10000
MOVHS orig_g, #0
MOVGE orig_g, lr
CMP orig_b, #0x10000
MOVHS orig_b, #0
MOVGE orig_b, lr
LDR palette, [str, #4*3]
LDR i, [str, #4*4]
MOV dmin, #&ffffffff
; for (i= ncolours; (i > 0); i--)
0
LDMIA palette!, {r, g, b}
SUBS r, r, orig_r ; how different is it?
RSBMI r, r, #0 ; makes multiply faster
MUL t, r, r
; scale for red ... |r|^2 * (0.212671 * 358 / 512) = |r|^2 * 0x0.26
MOV d, t, LSR #3 ; |r|^2 * 0x0.20
ADDNE d, d, t, LSR #6 ; |r|^2 * 0x0.24
ADDNE d, d, t, LSR #7 ; |r|^2 * 0x0.26
SUBS g, g, orig_g
RSBMI g, g, #0
MULNE t, g, g
; scale for green ... |g|^2 * (0.715160 * 358 / 512) = |g|^2 * 0x0.80
ADDNE d, d, t, LSR #1 ; |g|^2 * 0x0.80
SUBS b, b, orig_b
RSBMI b, b, #0
MULNE t, b, b
; scale for blue ... |b|^2 * (0.072169 * 358 / 512) = |b|^2 * 0x0.0d
ADDNE d, d, t, LSR #5 ; (|b|^2 / 512) * 0x0.08
ADDNE d, d, t, LSR #6 ; (|b|^2 / 512) * 0x0.0c
ADDNE d, d, t, LSR #8 ; (|b|^2 / 512) * 0x0.0d
;
; if (d < dmin) {
; best = i;
; dmin = d;
; if (dmin == 0) {
; i = 1;
; }
; }
;
CMP d, dmin
MOVLO best, i ; favour earlier entries in table
MOVLSS dmin, d ; see if zero difference
MOVEQ i, #1 ; yes, abort loop
SUBS i, i, #1
BGT %BT0
exact_match
LDMFD sp!, {d} ; d= pointer to structure
LDR palette, [d, #3*4]
LDR t, [d, #4*4] ; t= ncolours
SUB best, t, best ; best= index into array
ADD t, best, best, LSL #1
ADD palette, palette, t, LSL #2
LDMIA palette, {r, g, b} ; r,g,b= colour that is closest
SUB r, orig_r, r
SUB g, orig_g, g
SUB b, orig_b, b
STMIA d, {r, g, b} ; store error
LDMFD sp!, {v1-v6, pc}^
END